/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */

import { expect } from '@jest/globals';
import { parseJsonText } from '@ohos/hvigor';
import * as fse from 'fs-extra';
import { copy } from 'fs-extra';
import * as path from 'path';
import { resolve } from 'path';

import { ProjectBuildProfile } from '../../src/options/build/project-build-profile';
import { ModuleJson } from '../../src/options/configure/module-json-options';
import { OhosLogger } from '../../src/utils/log/ohos-logger';

import { appRoot, initByStageEmptyApp, initByStageEmptyService, initExecuteCommand, runHvigor, } from './common/common';
import { AppJsonModifier } from './common/modifier/app-json-modifier';
import { ModuleBuildProfileModifier } from './common/modifier/module-build-profile-modifier';
import { PackageJsonModifier } from './common/modifier/package-json-modifier';
import { Probes } from './common/probes';
import ModuleOptObj = ModuleJson.ModuleOptObj;
import ProjectProfileOpt = ProjectBuildProfile.ProjectProfileOpt;

const LOG: OhosLogger = OhosLogger.getLogger('merge-profile.OPENLAB_AIDE_ZOS_Build_product_target_06_004.ts');

describe('test merge profile Incremental', () => {
  test.concurrent('test stage app', async () => {
    await initByStageEmptyApp({
      cb: testMergeProfile,
      prepare: async (dir) => {
        await copy(resolve(appRoot(), 'test/resources/extra/har-packages'), dir);
        new PackageJsonModifier(dir, 'library')
          .updateDependency('library1', 'file:../library1')
          .updateDependency('stage_ets_native', 'file:../stage_ets_native.har')
          .outputSync();
        new PackageJsonModifier(dir, 'entry')
          .updateDependency('library', 'file:../library')
          .updateDependency('stage_ets_native_obfuscate', 'file:../stage_ets_native_obfuscate.har')
          .outputSync();
      }
    });
  });

  test.concurrent('test stage Service', async () => {
    await initByStageEmptyService({
      cb: testMergeProfile,
      prepare: async (dir) => {
        await copy(resolve(appRoot(), 'test/resources/extra/har-packages'), dir);
        new PackageJsonModifier(dir, 'library')
          .updateDependency('library1', 'file:../library1')
          .updateDependency('stage_ets_native', 'file:../stage_ets_native.har')
          .outputSync();
        new PackageJsonModifier(dir, 'entry')
          .updateDependency('library', 'file:../library')
          .updateDependency('stage_ets_native_obfuscate', 'file:../stage_ets_native_obfuscate.har')
          .outputSync();
        new ModuleBuildProfileModifier(dir, 'entry').updateTargetRuntimeOS('default', 'HarmonyOS');
      }
    });
  });
});

async function testMergeProfile(projectRoot: string) {
  const commands = initExecuteCommand({
    mode: 'module',
    module: 'entry',
    product: 'default',
    tasks: 'default@MergeProfile'
  });


  function shouldBuildFinished(projectRoot: string, commands: string[]) {
    const result = runHvigor(projectRoot, commands, { stderr: 'pipe' });
    expect(result.exitCode).toEqual(0);
    expect(result.stdout.includes('BUILD SUCCESSFUL')).toBeTruthy();
    expect(result.stdout.includes('Finished :entry:default@MergeProfile')).toBeTruthy();
    expect(result.stderr.includes('This library will not be merged.')).toBeFalsy();
    return result;
  }

  function shouldBuildUp2Date(projectRoot: string, commands: string[]) {
    const result = runHvigor(projectRoot, commands, { stderr: 'pipe' });
    expect(result.exitCode).toEqual(0);
    expect(result.stdout.includes('BUILD SUCCESSFUL')).toBeTruthy();
    expect(result.stdout.includes('UP-TO-DATE :entry:default@MergeProfile')).toBeTruthy();
    return result;
  }

  // 第一次执行任务
  shouldBuildFinished(projectRoot, commands);

  // 没有修改，第二次执行任务
  shouldBuildUp2Date(projectRoot, commands);

  // 修改module.json5，第三次执行任务
  const entryModuleJsonPath = path.resolve(projectRoot, 'entry', 'src', 'main', 'module.json5');
  const entryModuleJson = parseJsonText(fse.readFileSync(entryModuleJsonPath).toString()) as ModuleOptObj;
  entryModuleJson.module.deliveryWithInstall = false;
  fse.writeFileSync(entryModuleJsonPath, JSON.stringify(entryModuleJson));
  shouldBuildFinished(projectRoot, commands);

  // 没有修改，第四次执行任务
  shouldBuildUp2Date(projectRoot, commands);

  // 修改product的bundleName，第五次执行任务
  const buildJsonPath = path.resolve(projectRoot, 'build-profile.json5');
  const buildJson = parseJsonText(fse.readFileSync(buildJsonPath).toString()) as ProjectProfileOpt;
  LOG.info('buildJson.app.products:', buildJson.app.products);
  if (buildJson.app.products) {
    buildJson.app.products[0].bundleName = 'com.example.myapplication1';
    fse.writeFileSync(buildJsonPath, JSON.stringify(buildJson));
    shouldBuildFinished(projectRoot, commands);
  }

  // 新增字段multiProjects
  buildJson.app.multiProjects = true;
  fse.writeJsonSync(buildJsonPath, buildJson);
  shouldBuildFinished(projectRoot, commands);
  const probe = new Probes(projectRoot, resolve(projectRoot, 'entry'));
  expect(fse.readJsonSync(probe.getIntermediatesMergeProfile()).app.multiProjects).toEqual(true);

  shouldBuildUp2Date(projectRoot, commands);

  buildJson.app.multiProjects = false;
  fse.writeJsonSync(buildJsonPath, buildJson);
  shouldBuildFinished(projectRoot, commands);
  expect(fse.readJsonSync(probe.getIntermediatesMergeProfile()).app.multiProjects).toEqual(undefined);

  new AppJsonModifier(projectRoot).updateAttribute('multiProjects', true).outputSync();
  const result = shouldBuildFinished(projectRoot, commands);
  expect(result.stdout.includes('Field \'multiProjects\' should be configured in project\'s build-profile.json5.'));
  expect(fse.readJsonSync(probe.getIntermediatesMergeProfile()).app.multiProjects).toEqual(undefined);

  // 修改buildRoot，第6次执行任务
  commands.push('-p');
  commands.push('buildRoot=build1');
  shouldBuildFinished(projectRoot, commands);

  // 修改debuggable，第7次执行任务
  commands.push('-p');
  commands.push('debuggable=false');
  shouldBuildFinished(projectRoot, commands);

  // 没有修改，第8次执行任务
  shouldBuildUp2Date(projectRoot, commands);
}
